import vtkPolyData from "@kitware/vtk.js/Common/DataModel/PolyData";
import vtkPoints from "@kitware/vtk.js/Common/Core/Points";
import vtkCellArray from "@kitware/vtk.js/Common/Core/CellArray";
import vtkDataArray from "@kitware/vtk.js/Common/Core/DataArray";
import { TEdge } from "./Core/TEdge";

// mark
export interface GYData {
  nodes: number[];
  faceIds: number[];
  triangles: number[];
  faceTriNums: number[];
  edgeIds: number[];
  outlines: number[];
  faceEdges: number[];
  vertexs: number[];
  faceEdgesNums: number[];
  edgeLineNums: number[];
  normals: [];
  edgeTypes: number[];
  faceParts: number[];
}

export class vtxlyLoader {
  polyData = vtkPolyData.newInstance();
  outLinePolyData = vtkPolyData.newInstance();
  edgeData: TEdge;
  points = vtkPoints.newInstance();
  cells = vtkCellArray.newInstance();
  lines = vtkCellArray.newInstance();
  gyData: GYData;
  faceIdPointsMap: Map<any, any>;
  vertexsMap: Map<any, any>;
  trianglesMap: Map<any, any>;
  faceTrianglesPointsMap: Map<any, any>;
  faceTrianglesMap: Map<any, any>;
  faceEdgeNodeMap: Map<any, any>; // mark
  linePoints: number[] = []; // * 轮廓线顶点坐标
  faceParts: number[] = [];

  constructor(json: string) {
    const jsonObj = JSON.parse(json);
    // console.log("json", json);
    // console.log("jsonObj", jsonObj);
    // console.log("edgeIds", jsonObj.edgeIds);
    this.gyData = {
      nodes: JSON.parse(jsonObj.nodes),
      faceIds: JSON.parse(jsonObj.faceIds),
      triangles: JSON.parse(jsonObj.triangles),
      faceTriNums: JSON.parse(jsonObj.faceTriNums),
      edgeIds: JSON.parse(jsonObj.edgeIds),
      outlines: JSON.parse(jsonObj.outlines),
      faceEdges: JSON.parse(jsonObj.faceEdges),
      vertexs: JSON.parse(jsonObj.vertexs),
      faceEdgesNums: JSON.parse(jsonObj.faceEdgesNums),
      edgeLineNums: JSON.parse(jsonObj.edgeLineNums),
      normals: JSON.parse(jsonObj.normals),
      edgeTypes: JSON.parse(jsonObj.edgeTypes),
      faceParts: JSON.parse(jsonObj.faceParts),
    };
    const {
      faceIdPointsMap,
      vertexsMap,
      trianglesMap,
      faceTrianglesPointsMap,
      faceTrianglesMap,
      faceEdgeNodeMap,
    } = this.parseCellsFromGYData();
    this.faceIdPointsMap = faceIdPointsMap;
    this.vertexsMap = vertexsMap;
    this.trianglesMap = trianglesMap;
    this.faceTrianglesPointsMap = faceTrianglesPointsMap;
    this.faceTrianglesMap = faceTrianglesMap;
    this.faceEdgeNodeMap = faceEdgeNodeMap;
    this.createPointData();
    this.createCellData();
    this.createOutLines();
    this.polyData.setPoints(this.points);
    this.polyData.getPointData().setNormals(
      vtkDataArray.newInstance({
        name: "Normals",
        values: [...this.gyData.normals],
        numberOfComponents: 3, // 法线向量的分量个数
      })
    );
    this.polyData.setPolys(this.cells);
    this.outLinePolyData.setPoints(this.points);
    this.outLinePolyData.setLines(this.lines);
    this.edgeData = new TEdge(
      this.outLinePolyData,
      this.gyData.edgeIds,
      this.gyData.edgeLineNums,
      this.gyData.edgeTypes,
      this.faceEdgeNodeMap,
      [...this.linePoints]
    );
  }

  // * 构建几何结构
  createPointData(mode = "edges") {
    const TMP_nodes = [...this.gyData.nodes];
    const TMP_arr = new Float32Array(TMP_nodes.length).fill(0.0);
    TMP_nodes.map((v: any, index: number) => {
      TMP_arr[index] = Number(v);
    });
    this.points.setData(TMP_arr, 3);
  }

  parseCellsFromGYData() {
    const TMP_triangles: number[] = [...this.gyData.triangles];
    const TMP_nodes: number[] = [...this.gyData.nodes];
    const TMP_edgeIds: number[] = [...this.gyData.edgeIds];
    const TMP_outlines: number[] = [...this.gyData.outlines];
    const TMP_vertexs: number[] = [...this.gyData.vertexs];
    const TMP_edgeLineNums: number[] = [...this.gyData.edgeLineNums];
    const TMP_faceEdgeNums: number[] = [...this.gyData.faceEdgesNums];
    const TMP_faceEdges: number[] = [...this.gyData.faceEdges];
    const TMP_faceIds: number[] = [...this.gyData.faceIds];
    const TMP_faceTriNums: number[] = [...this.gyData.faceTriNums];

    // * 处理顶点坐标
    // @ 注 key 是顶点id
    const vertexsMap = new Map<any, any>();

    for (let i = 0; i < TMP_vertexs.length; i += 2) {
      vertexsMap.set(TMP_vertexs[i + 1], [
        TMP_nodes[3 * TMP_vertexs[i]],
        TMP_nodes[3 * TMP_vertexs[i] + 1],
        TMP_nodes[3 * TMP_vertexs[i] + 2],
      ]);
    }

    // devtool.info("vertexsMap", vertexsMap);

    // * ✅ 处理每个三角形所包含的点坐标
    const trianglePointsMap = new Map();
    for (let i = 0; i < TMP_triangles.length / 3; i++) {
      trianglePointsMap.set(i, [
        [
          TMP_nodes[3 * TMP_triangles[i]],
          TMP_nodes[3 * TMP_triangles[i] + 1],
          TMP_nodes[3 * TMP_triangles[i] + 2],
        ],
        [
          TMP_nodes[3 * TMP_triangles[i + 1]],
          TMP_nodes[3 * TMP_triangles[i + 1] + 1],
          TMP_nodes[3 * TMP_triangles[i + 1] + 2],
        ],
        [
          TMP_nodes[3 * TMP_triangles[i + 2]],
          TMP_nodes[3 * TMP_triangles[i + 2] + 1],
          TMP_nodes[3 * TMP_triangles[i + 2] + 2],
        ],
      ]);
    }

    // * ✅ 处理每个三角所包含的顶点
    const trianglesMap = new Map();
    for (let i = 0; i < TMP_triangles.length / 3; i++) {
      trianglesMap.set(i, [
        TMP_triangles[i * 3],
        TMP_triangles[i * 3 + 1],
        TMP_triangles[i * 3 + 2],
      ]);
    }

    // devtool.info("trianglesMap", trianglesMap);

    // * 🟡 处理每条边所包含的点
    // @ key 为下标索引
    const edgesMap = new Map();
    for (let i = 0; i < TMP_edgeLineNums.length; i++) {
      const count =
        i === 0
          ? TMP_edgeLineNums[i]
          : TMP_edgeLineNums[i] - TMP_edgeLineNums[i - 1];
      edgesMap.set(i, TMP_outlines.splice(0, count * 2));
    }
    // devtool.info("edgesMap", edgesMap);

    // *  🟡 处理对应ID的边所对应的点
    // @ key 为id
    const edgeIdsMap = new Map();
    for (let i = 0; i < TMP_edgeIds.length; i++) {
      edgeIdsMap.set(TMP_edgeIds[i], edgesMap.get(i));
    }
    // devtool.info("edgeIdsMap", edgeIdsMap);

    // * 🟡 处理每个面所包含的边
    const facesMap = new Map();
    for (let i = 0; i < TMP_faceEdgeNums.length; i++) {
      const count =
        i === 0
          ? TMP_faceEdgeNums[i]
          : TMP_faceEdgeNums[i] - TMP_faceEdgeNums[i - 1];
      facesMap.set(i, TMP_faceEdges.splice(0, count));
    }

    // devtool.info("facesMap", facesMap);

    // * 🔴 处理每个面所包含的点
    const facePointsMap = new Map();
    // for (let x = 0; x < TMP_faceEdgeNums.length; x++) {
    //   const edges = facesMap.get(x)
    //   let TMP_arr = []
    //   // !! 这里是边id 非索引
    //   edges.forEach((id) => {
    //     // * 有可能会有很多组点 要拆成两两一组
    //     const ids = edgeIdsMap.get(id)
    //     const flatArr = this.flatToTwoPoint(ids)
    //     flatArr.forEach((t) => {
    //       TMP_arr.push(t)
    //     })
    //   })
    //   // console.log("TMP_arr", TMP_arr)
    //   // !! 重建拓扑关系
    //   TMP_arr = this.getTheVertexRightPosition(TMP_arr)
    //   facePointsMap.set(x, TMP_arr)
    // }

    // devtool.info("facePointsMap", facePointsMap);

    const faceIdPointsMap = new Map();
    for (let y = 0; y < TMP_faceIds.length; y++) {
      faceIdPointsMap.set(TMP_faceIds[y], facePointsMap.get(y));
    }
    // devtool.info("faceIdPointsMap", faceIdPointsMap);

    // * 处理每个面所包含的三角数据索引坐标
    // @ 注 key是索引
    const faceTrianglesPointsMap = new Map();
    // @ 注 key是索引
    const faceTrianglesMap = new Map();
    for (let i = 0; i < TMP_faceTriNums.length; i++) {
      const count =
        i === 0
          ? TMP_faceTriNums[i]
          : TMP_faceTriNums[i] - TMP_faceTriNums[i - 1];
      const all = TMP_triangles.splice(0, count * 3);
      const triangleArr = [];
      for (let j = 0; j < all.length / 3; j++) {
        triangleArr.push([all[3 * j], all[3 * j + 1], all[3 * j + 2]]);
      }
      faceTrianglesPointsMap.set(i, triangleArr);

      const TMP_a = [];
      let flag = i === 0 ? 0 : TMP_faceTriNums[i - 1];
      // * 处理每个面所包含的三角索引ID
      for (let t = 0; t < count; t++) {
        TMP_a.push(flag++);
      }
      faceTrianglesMap.set(i, TMP_a);
    }
    // devtool.info("faceTrianglesPointsMap", faceTrianglesPointsMap);

    // * 处理每个面包含的线段及线段所包含的顶点坐标，用于选取线
    /**
     * {
        faceId: [
          { 
            edgeIndex: 0,
            edgeStartIndex: 0,
            edgeEndIndex: 20,
            edgeId: 1,
            nodes: [
              [x1, y1, z1],
              [x2, y2, z2],
            ],
            visible: true
          }
        ]
      }
     */
    const faceEdgeNodeMap = new Map();
    for (let i = 0; i < TMP_faceIds.length; i++) {
      // 获取每个面所包含的边id
      const perFaceEdges = facesMap.get(i);
      const faceEdgeNodes = [];
      for (let e = 0; e < perFaceEdges.length; e++) {
        const edgeId = perFaceEdges[e];
        const edgeIndex = TMP_edgeIds.indexOf(edgeId);
        const edgeStartIndex =
          edgeIndex === 0 ? 0 : TMP_edgeLineNums[edgeIndex - 1];
        const edgeEndIndex = TMP_edgeLineNums[edgeIndex];
        const perOutlines = edgeIdsMap.get(edgeId);
        const nodes = [];
        for (let o = 0; o < perOutlines.length; o++) {
          nodes.push([
            TMP_nodes[3 * perOutlines[o]],
            TMP_nodes[3 * perOutlines[o] + 1],
            TMP_nodes[3 * perOutlines[o] + 2],
          ]);
        }
        const edgeNodeMap = {
          edgeId,
          edgeIndex,
          edgeStartIndex,
          edgeEndIndex,
          nodes,
          visible: true,
        };
        faceEdgeNodes.push(edgeNodeMap);
      }
      faceEdgeNodeMap.set(TMP_faceIds[i], faceEdgeNodes);
    }
    // console.log("faceEdgeNodeMap", faceEdgeNodeMap);

    return {
      trianglesMap,
      trianglePointsMap,
      edgeIdsMap,
      vertexsMap,
      edgesMap,
      facesMap,
      facePointsMap,
      faceIdPointsMap,
      faceTrianglesPointsMap,
      faceTrianglesMap,
      faceEdgeNodeMap,
    };
  }

  // * 构建拓扑结构
  createCellData() {
    for (let i = 0; i < this.trianglesMap.size; i++) {
      this.cells.insertNextCell(this.trianglesMap.get(i));
    }
  }

  createOutLines() {
    console.log("this.gyData.outlines", this.gyData.outlines);
    for (let i = 0; i < this.gyData.outlines.length / 2; i++) {
      this.linePoints.push(
        this.gyData.nodes[this.gyData.outlines[2 * i] * 3],
        this.gyData.nodes[this.gyData.outlines[2 * i] * 3 + 1],
        this.gyData.nodes[this.gyData.outlines[2 * i] * 3 + 2]
      );
      this.linePoints.push(
        this.gyData.nodes[this.gyData.outlines[2 * i + 1] * 3],
        this.gyData.nodes[this.gyData.outlines[2 * i + 1] * 3 + 1],
        this.gyData.nodes[this.gyData.outlines[2 * i + 1] * 3 + 2]
      );
      this.lines.insertNextCell([
        this.gyData.outlines[2 * i],
        this.gyData.outlines[2 * i + 1],
      ]);
    }
  }
}
